/*
 * Copyright 2007-2009 Thomas Krause (thomas@berlin-reloaded.de)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gidoo.cms.extra.tags;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.gidoo.cms.IEditPlugin;
import org.gidoo.cms.login.GidooCMSSession;

/**
 * Editor component for modifying tags.
 * @author <a href="mailto:thomas@berlin-reloaded.de">Thomas Krause</a>
 */
public class TagPlugin implements IEditPlugin, Serializable
{

  private TagPluginPanel panel;
  private String currentSelectedPagePath;

  @Override
  public void setCurrentSelectedPage(Node currentSelectedPage)
  {
    this.currentSelectedPagePath = null;
    if(currentSelectedPage != null)
    {
      try
      {
        this.currentSelectedPagePath = currentSelectedPage.getPath();
      }
      catch(RepositoryException ex)
      {
        Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
      }
    }
  }

  @Override
  public String getPluginName()
  {
    return "Tags";
  }

  @Override
  public Panel getPluginPanel(String id)
  {
    panel = new TagPluginPanel(id, currentSelectedPagePath);

    return panel;
  }

  public class TagPluginPanel extends Panel
  {

    private final Form form = new Form("form");
    private List<String> tagsOfPage;
    private Set<String> websiteTags;
    private String currentNodePath;

    public TagPluginPanel(String id, final String currentNodePath)
    {
      super(id);

      this.currentNodePath = currentNodePath;

      tagsOfPage = new LinkedList<String>();
      websiteTags = new HashSet<String>();

      final AutoCompleteTextField<String> acNewTag =
        new AutoCompleteTextField<String>("acNewTag", new Model(""))
        {

          @Override
          protected Iterator getChoices(String input)
          {
            Set<String> set = new HashSet<String>();
            
            set.add(input);
          
            if("".equals(input))
            {
              set.addAll(websiteTags);
            }
            else
            {
              Iterator<String> it = websiteTags.iterator();
              while(it.hasNext())
              {
                String s = it.next();
                if(s.toLowerCase().startsWith(input.toLowerCase()))
                {
                  set.add(s);
                }
              }
            }
            LinkedList<String> l = new LinkedList<String>(set);

            Collections.sort(l);

            return l.listIterator();
          }
        };


      form.setOutputMarkupId(true);
      acNewTag.setOutputMarkupId(true);

      acNewTag.add(new AjaxFormSubmitBehavior("onchange")
      {

        @Override
        protected void onSubmit(AjaxRequestTarget target)
        {
          saveTag(acNewTag);
          target.addComponent(form);
          updateView();

        }

        @Override
        protected void onError(AjaxRequestTarget arg0)
        {
          arg0.addComponent(form);
        }
      });

      form.add(acNewTag);

      ListView lsvTags = new ListView("lsvTags")
      {

        @Override
        protected void populateItem(ListItem item)
        {
          final String tagName = tagsOfPage.get(item.getIndex());
          item.add(new Label("lblTag", new Model(tagName)));
          item.add(new AjaxLink("lnkDeleteTag")
          {

            @Override
            public void onClick(AjaxRequestTarget arg0)
            {
              try
              {
                Node page = ((GidooCMSSession) getSession()).getJcrRootNode().getNode(currentNodePath.substring(1));
                Node md = page.getNode("cms:md");
                if(md.hasNode("tags") && md.getNode("tags").hasNode(tagName))
                {
                  md.getNode("tags").getNode(tagName).remove();
                  md.save();
                }
              }
              catch(PathNotFoundException ex)
              {
                Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
              }
              catch(RepositoryException ex)
              {
                Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
              }

              updateView();
              arg0.addComponent(form);
            }
          });
        }
      };

      updateView();

      lsvTags.setList(tagsOfPage);

      form.add(lsvTags);

      add(form);
    }

    private void saveTag(AutoCompleteTextField<String> acNewTag)
    {
      try
      {
        // save tags
        String newTagName = acNewTag.getModelObject();
        acNewTag.setModelObject("");

        Node page =
          ((GidooCMSSession) getSession()).getJcrRootNode().getNode(currentNodePath.substring(1));
        Node md =
          page.getNode("cms:md");

        // add if not existing
        if(!md.hasNode("tags"))
        {
          md.addNode("tags");
          md.save();
        }

        if(md.hasNode("tags") && !md.getNode("tags").hasNode(newTagName))
        {
          md.getNode("tags").addNode(newTagName);
          md.save();
        }

        acNewTag.setModelObject("");
      }
      catch(PathNotFoundException ex)
      {
        Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
      }
      catch(RepositoryException ex)
      {
        Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
      }
    }

    private void updateView()
    {
      tagsOfPage.clear();
      websiteTags.clear();

      form.setVisible(false);

      if(currentNodePath != null)
      {
        form.setVisible(true);

        try
        {
          // get tags of this page
          Node page =
            ((GidooCMSSession) getSession()).getJcrRootNode().getNode(currentNodePath.substring(1));
          tagsOfPage.addAll(Helper.getTagsOfPage(page));

          // get tags existing in whole website
          websiteTags.addAll(Helper.getAllsTagsOfSite((GidooCMSSession) getSession()));

        }
        catch(RepositoryException ex)
        {
          Logger.getLogger(TagPlugin.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
    }
  }
}
